package edu.washington.cs.sounddetector.server.api.methodlogic;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import edu.washington.cs.sounddetector.server.api.method.UnregisterReceiverPhone;
import edu.washington.cs.sounddetector.server.api.method.Untrain;
import edu.washington.cs.sounddetector.server.api.methodresult.UnregisterReceiverPhoneResult;
import edu.washington.cs.sounddetector.server.api.methodresult.UntrainResult;
import edu.washington.cs.sounddetector.server.database.Model;
import edu.washington.cs.sounddetector.server.database.Notifications;
import edu.washington.cs.sounddetector.server.database.ReceiverPhone;
import edu.washington.cs.sounddetector.server.database.Sound;
import edu.washington.cs.sounddetector.server.weka.WekaHelper;

/**
 * DeleteLogic implements logic that performs delete operations on the database.
 * 
 * @author the.dylan.price@gmail.com
 * 
 */
public class DeleteLogic
{
    private static final Log log = LogFactory.getLog(WriteLogic.class);

    private PersistenceManagerFactory pmf;

    public DeleteLogic(PersistenceManagerFactory pmf)
    {
        this.pmf = pmf;
    }

    public UnregisterReceiverPhoneResult unregisterReceiverPhone(
            UnregisterReceiverPhone unregisterReceiverPhone)
    {
        String phoneId = unregisterReceiverPhone.getPhoneId();
        PersistenceManager pm = pmf.getPersistenceManager();
        Transaction tx = pm.currentTransaction();
        try
        {
            tx.begin();
            // TODO: change when we implement users
            ReceiverPhone receiverPhone = ReceiverPhone.query(pm, "1", phoneId);

            if (receiverPhone == null)
                return UnregisterReceiverPhoneResult.failurePhoneDoesNotExist(phoneId);

            // TODO: change when we implement users
            Collection<Notifications> notifications = Notifications.query(pm, "1", receiverPhone);

            pm.deletePersistentAll(notifications);
            pm.deletePersistent(receiverPhone);
            tx.commit();
            return UnregisterReceiverPhoneResult.success();
        }
        finally
        {
            if (tx.isActive())
                tx.rollback();
            pm.close();
        }
    }

    public UntrainResult untrain(Untrain untrain)
    {
        List<Long> soundIds = untrain.getSoundIds();
        PersistenceManager pm = pmf.getPersistenceManager();
        Transaction tx = pm.currentTransaction();
        try
        {
            tx.begin();

            Set<String> detectorIds = new HashSet<String>();
            for (Long id : soundIds)
            {
                Sound sound = pm.getObjectById(Sound.class, id);
                detectorIds.add(sound.getSoundClass().getDetectorId());
                pm.deletePersistent(sound);
            }
            for (String detectorId : detectorIds)
            {
                // TODO: change when we implement users
                Model model = Model.query(pm, "1", detectorId);
                WekaHelper.trainModel(pm, model);
                pm.makePersistent(model);
            }

            tx.commit();
            return UntrainResult.success();
        }
        catch (Exception e)
        {
            log.warn("Could not build classifier", e);
            return UntrainResult.failureCantBuildClassifier(e.getMessage());
        }
        finally
        {
            if (tx.isActive())
                tx.rollback();
            pm.close();
        }
    }
}
